#pragma once

#include <pthread.h>
#include <curl/curl.h>
#include <string>
#include "BBS2chProxyKeyManager.h"
#include "BBS2chProxyFormData.h"

class BBS2chProxyAuth {
  private:
	std::string sid;
	time_t expire;
	pthread_mutex_t mutex;
	
  public:
	BBS2chProxyAuth() : expire(0) {
		pthread_mutex_init(&mutex, NULL);
	};
	~BBS2chProxyAuth() {
		pthread_mutex_destroy(&mutex);
	};
	std::string requestBodyForURL(const char *url, CURL *curl);
	const std::string& getSID();
	
  private:
	bool updateSID(CURL *curl);
};

class IBBS2chProxyCookieAuth {
  protected:
	time_t _lastUpdated;
	std::string _mail;
	std::string _passwd;
	pthread_mutex_t _mutex;
	bool _isUpdating;
	std::string _headerTitle;
	std::string _uniqueId;
	int _updateInterval;
  public:
	IBBS2chProxyCookieAuth() : _lastUpdated(), _isUpdating(), _updateInterval(60*60*12) {
		pthread_mutex_init(&_mutex, NULL);
	};
	virtual ~IBBS2chProxyCookieAuth() {
		pthread_mutex_destroy(&_mutex);
	};
	int loginWith(const std::string &mail, const std::string &passwd);
	void prepareForLogin(CURL *curl, const std::string &authURL, BBS2chProxyFormData &requestBody);
	void update(bool force);
	std::string responseHTML();
	virtual bool login() = 0;
	virtual void logout() = 0;
	virtual bool syncCookie(BBS2chProxyKeyManager::CookieJar &jar) = 0;
	virtual bool isLoggedIn() = 0;
};

class BBS2chProxyAcornAuth : public IBBS2chProxyCookieAuth {
  private:
	std::string _cookie;
  public:
	BBS2chProxyAcornAuth() : IBBS2chProxyCookieAuth() {
		_headerTitle = "どんぐりシステム";
		_uniqueId = "donguri";
	};
	bool login();
	void logout();
	bool syncCookie(BBS2chProxyKeyManager::CookieJar &jar);
	bool isLoggedIn();
};

class BBS2chProxyBeAuth : public IBBS2chProxyCookieAuth {
  private:
	std::string _dmdm;
	std::string _mdmd;
  public:
	BBS2chProxyBeAuth() : IBBS2chProxyCookieAuth() {
		_headerTitle = "Be";
		_uniqueId = "be";
	};
	bool login();
	void logout();
	bool syncCookie(BBS2chProxyKeyManager::CookieJar &jar);
	bool isLoggedIn();
};

class BBS2chProxyUpliftAuth : public IBBS2chProxyCookieAuth {
  private:
	std::string _cookie;
  public:
	BBS2chProxyUpliftAuth() : IBBS2chProxyCookieAuth() {
		_headerTitle = "UPLIFT";
		_uniqueId = "uplift";
	};
	bool login();
	void logout();
	bool syncCookie(BBS2chProxyKeyManager::CookieJar &jar);
	bool isLoggedIn();
};

class BBS2chProxyCookieAuthManager {
  private:
	BBS2chProxyAcornAuth _acornAuth;
	BBS2chProxyBeAuth _beAuth;
	BBS2chProxyUpliftAuth _upliftAuth;
  public:
	int loginWith(const std::string &service, const std::string &mail, const std::string &passwd);
	void logout(const std::string &service);
	void syncCookies(BBS2chProxyKeyManager::CookieJar &jar);
	std::string responseHTML();
};
